<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf8">
    <!--

    @license twgl.js Copyright (c) 2015, Gregg Tavares All Rights Reserved.
    Available via the MIT license.
    see: http://github.com/greggman/twgl.js for details

    -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
    <meta property="og:title" content="TWGL.js - no-box-skybox" />
    <meta property="og:type" content="website" />
    <meta property="og:image" content="http://twgljs.org/examples/screenshots/no-box-skybox.png" />
    <meta property="og:description" content="TWGL.js - no-box-skybox" />
    <meta property="og:url" content="http://twgljs.org" />

    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@greggman">
    <meta name="twitter:creator" content="@greggman">
    <meta name="twitter:domain" content="twgljs.org">
    <meta name="twitter:title" content="TWGL.js - no-box-skybox">
    <meta name="twitter:url" content="http://twgljs.org/examples/no-box-skybox.html">
    <meta name="twitter:description" content="TWGL.js - no-box-skybox">
    <meta name="twitter:image:src" content="http://twgljs.org/examples/screenshots/no-box-skybox.png">

    <link href="/resources/images/twgljs-icon.png" rel="shortcut icon" type="image/png">

    <title>twgl.js - no-box-skybox</title>
    <style>
      * {
          box-sizing: border-box;
          -moz-box-sizing: border-box;
      }
      body {
          margin: 0;
          font-family: monospace;
      }
      canvas {
          display: block;
          width: 100vw;
          height: 100vh;
      }
      #b {
        position: absolute;
        top: 10px;
        width: 100%;
        text-align: center;
        z-index: 2;
      }
      #ui {
        position: absolute;
        top: 30px;
        left: 30px;
        width: 300px;
        z-index: 3;
        padding: 1em;
        color: white;
        background-color: rgba(0, 0, 0, 0.5);
      }
      input {
        width: 100%;
      }
      @media only screen and (max-width: 400px) {
          #ui {
            width: 90%;
            padding: 0.5em;
            left: 5%;
          }
      }
    </style>
  </head>
  <body>
    <canvas id="c"></canvas>
    <div id="b"><a href="http://twgljs.org">twgl.js</a> - no-box-skybox</div>
    <div id="ui">
      <div>fov: <span id="fov"></span></div>
      <div><input id="fov-input" type="range" min="5" max="170" value="30"></input></div>
    </div>
  </body>
  <script id="vs" type="notjs">
attribute vec4 a_position;
varying vec4 v_position;
void main() {
  v_position = a_position;
  gl_Position = a_position;
}
  </script>
  <script id="fs" type="notjs">
precision mediump float;

uniform samplerCube u_skybox;
uniform mat4 u_viewDirectionProjectionInverse;

varying vec4 v_position;
void main() {
  vec4 t = u_viewDirectionProjectionInverse * v_position;
  gl_FragColor = textureCube(
      u_skybox,
      normalize(t.xyz / t.w));
}
  </script>
  <script type="module">
    import * as twgl from '../dist/4.x/twgl-full.module.js';
    const $ = document.getElementById.bind(document);
    twgl.setDefaults({attribPrefix: "a_"});
    const m4 = twgl.m4;
    const gl = document.querySelector("#c").getContext("webgl");
    const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
    const plane = twgl.primitives.createXYQuadBufferInfo(gl);

    // Shared values
    const camera = m4.identity();
    const view = m4.identity();
    const viewDirection = m4.identity();
    const viewDirectionProjection = m4.identity();
    const viewDirectionProjectionInverse = m4.identity();

    const uniforms = {
      u_skybox: twgl.createTexture(gl, {
        target: gl.TEXTURE_CUBE_MAP,
        src: [
          'images/niagarafalls2s/posx.jpg',
          'images/niagarafalls2s/negx.jpg',
          'images/niagarafalls2s/posy.jpg',
          'images/niagarafalls2s/negy.jpg',
          'images/niagarafalls2s/posz.jpg',
          'images/niagarafalls2s/negz.jpg',
        ],
      }),
      u_viewDirectionProjectionInverse: viewDirectionProjectionInverse,
    };

    let fov = 90;
    const fovElem = $("fov");
    const fovNode = document.createTextNode(fov);
    const fovInput = $("fov-input");
    fovInput.value = fov;
    fovElem.appendChild(fovNode);

    fovInput.addEventListener('input', function() {
      fov = fovInput.value;
      fovNode.nodeValue = fov;
    });

    function render(time) {
      time *= 0.001;
      twgl.resizeCanvasToDisplaySize(gl.canvas);
      gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

      const orbitSpeed = time * 0.1;
      const radius = 20;
      const projection = m4.perspective(fov * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 100);
      const eye = [Math.cos(orbitSpeed) * radius, 4, Math.sin(orbitSpeed) * radius];
      const target = [0, 0, 0];
      const up = [0, 1, 0];

      m4.lookAt(eye, target, up, camera);
      m4.inverse(camera, view);
      m4.setTranslation(view, [0, 0, 0], viewDirection);
      m4.multiply(projection, viewDirection, viewDirectionProjection);
      m4.inverse(viewDirectionProjection, viewDirectionProjectionInverse);

      gl.useProgram(programInfo.program);
      twgl.setBuffersAndAttributes(gl, programInfo, plane);
      twgl.setUniforms(programInfo, uniforms);
      twgl.drawBufferInfo(gl, plane);

      requestAnimationFrame(render);
    }
    requestAnimationFrame(render);

  </script>
</html>


